<template>
  <a-row>
    <a-col :span="10">
      <a-space class="ToolBar">
        <a-select
          v-model:value="state.dbId"
          style="width: 128px"
          :options="keyTypes"
          @change="onKeyTypeChange"
        ></a-select>
        <a-button @click="loadKeys" :disabled="state.disableLoad"
          >Load 10k keys</a-button
        >
      </a-space>
      <div
        style="
          height: 720px;
          overflow: auto;
          margin: 4px;
          border: 1px silver solid;
        "
      >
        <a-tree
          block-node
          :tree-data="treeData"
          v-model:selectedKeys="selectedKeys"
          @select="getNodeValue"
          showLine
        >
        </a-tree>
      </div>
    </a-col>
    <a-col :span="14" style="height: 800px">
      <a-space>
        <a-button
          type="link"
          :title="$t('223')"
          @click="state.inEditMode = true"
          v-if="!state.inEditMode"
          >{{ $t("223") }}</a-button
        >
        <a-button
          type="link"
          :title="$t('224')"
          @click="editValue"
          v-if="state.inEditMode"
          >{{ $t("224") }}</a-button
        >
        <a-button
          type="link"
          @click="state.inEditMode = false"
          v-if="state.inEditMode"
          >{{ $t("225") }}</a-button
        >
        <a-button type="link" danger :title="$t('226')" @click="removeKey">{{
          $t("226")
        }}</a-button>
        <a-button type="link" danger :title="$t('227')" @click="removeByHead">{{
          $t("227")
        }}</a-button>
      </a-space>
      <p>{{ selectedKeys[0] }}</p>
      <JsonEditor
        v-model="currentValue"
        :canEdit="state.inEditMode"
      ></JsonEditor>
    </a-col>
  </a-row>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue";
import CommonDefine from "@/component/CommonDefine";
import { js_beautify } from "js-beautify";
import JsonEditor from "@/component/field/JsonEditor.vue";

const keyTypes = [
  { label: "索引", value: 10 },
  { label: "定义", value: 11 },
  { label: "列值", value: 12 },
  { label: "日志", value: 13 },
  { label: "唯一值", value: 14 },
  { label: "缓存", value: 15 },
  { label: "回收站", value: 16 },
];
const treeData = reactive([]);
const state = reactive({
  inEditMode: false,
  lastIndex: 0,
  disableLoad: false,
  dbId: 10,
});
const selectedKeys = ref([]);
const currentValue = ref("");
const keyDisplayMap = new Map(
  Object.entries({
    11: "模型",
    12: "字段",
    13: "记录基本信息",
    14: "系统用户",
    15: "日志",
    16: "上传的文件",
    17: "用户消息",
    31: "Parquet需要刷新",
    32: "名称缓存",
    33: "自增减ID",
    51: "访问请求",
    52: "访问凭证",
    53: "记录规则",
    54: "记录版本",
    55: "订阅者",
    56: "列值",
    71: "手机号唯一性",
    72: "模型标记唯一性",
    73: "字段标记唯一性",
    74: "列值唯一性",
    75: "记录规则唯一性",
  })
);

const getKeyDisplay = (k) => {
  if (keyDisplayMap.has(k)) {
    return keyDisplayMap.get(k);
  } else {
    return k;
  }
};

const loadKeys = () => {
  state.disableLoad = true;
  CommonDefine.apiGetArm(
    `/api-admin/db/keys?db=${state.dbId}&from=${state.lastIndex}`,
    (d) => {
      d.forEach((key) => {
        let keys = key.split("/");
        keys.splice(0, 1); //所有的key以斜杠开头,所以第一个元素为空字符串
        let keyL1 = keys[0];
        let nodeL1, nodeL2, nodeL3;
        let idx = treeData.findIndex((item) => item.key == keyL1);
        if (idx < 0) {
          nodeL1 = { title: getKeyDisplay(keyL1), key: keyL1, children: [] };
          treeData.push(nodeL1);
        } else {
          nodeL1 = treeData[idx];
        }
        if (keys[1] != undefined && keys[1] != null) {
          let keyL2 = keys[1];
          idx = nodeL1.children.findIndex((item) => item.key == keyL2);
          if (idx < 0) {
            if (keys.length == 2) {
              nodeL1.children.push({
                title: key.replace("/" + keyL1, "").replace("/", ""),
                key: key,
              });
            } else {
              nodeL2 = { title: keyL2, key: keyL2, children: [] };
              nodeL1.children.push(nodeL2);
            }
          } else {
            nodeL2 = nodeL1.children[idx];
          }
          if (keys[2] != undefined && keys[2] != null) {
            let keyL3 = keys[2];
            idx = nodeL2.children.findIndex((item) => item.key == keyL3);
            if (idx < 0) {
              if (keys.length == 3) {
                nodeL2.children.push({
                  title: key
                    .replace("/" + keyL1, "")
                    .replace("/" + keyL2, "")
                    .replace("/", ""),
                  key: key,
                });
              } else {
                nodeL3 = { title: keyL3, key: keyL3, children: [] };
                nodeL2.children.push(nodeL3);
              }
            } else {
              nodeL3 = nodeL2.children[idx];
            }
            if (keys[3] != undefined && keys[3] != null) {
              nodeL3.children.push({
                title: key
                  .replace("/" + keyL1, "")
                  .replace("/" + keyL2, "")
                  .replace("/" + keyL3, "")
                  .replace("/", ""),
                key: key,
              });
            }
          }
        }
      });
      state.lastIndex += d.length;
      state.disableLoad = d.length < 10000;
    }
  );
};

const getNodeValue = () => {
  let queryKey = selectedKeys.value[0];
  if (!queryKey || queryKey.lastIndexOf("/") < 0) {
    return;
  }
  CommonDefine.apiGetArm(
    `/api-admin/db/value?db=${state.dbId}&key-b64=${btoa(queryKey)}`,
    (d) => {
      state.inEditMode = false;
      let j = js_beautify(d, {
        indent_size: 2,
        brace_style: "expand",
        keep_array_indentation: true,
      });
      currentValue.value = j;
    }
  );
};

const editValue = () => {
  let pd = {
    k: selectedKeys.value[0],
    v: currentValue.value,
    db: state.dbId,
  };
  CommonDefine.apiPostArm("/api-admin/db/edit-value", pd, (d) => {
    state.inEditMode = false;
  });
};

const removeKey = () => {
  CommonDefine.apiPostArm(
    "/api-admin/db/remove",
    { db: state.dbId, keys: selectedKeys.value },
    (d) => {
      loadKeys();
    }
  );
};

const removeByHead = () => {
  CommonDefine.apiPostArm(
    "/api-admin/db/remove-by-head",
    { db: state.dbId, key: selectedKeys.value[0] },
    (d) => {
      loadKeys();
    }
  );
};

const onKeyTypeChange = () => {
  state.disableLoad = false;
  CommonDefine.clearArray(treeData);
  state.lastIndex = 0;
  loadKeys();
};

onMounted(() => {
  loadKeys();
});
</script>
